package com.quanyan.order.service.impl;

import com.quanyan.api.APIRequest;
import com.quanyan.api.APIResponse;
import com.quanyan.api.enums.ApiResponseEnum;
import com.quanyan.assets.service.UserAssetsService;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.enums.PlatformTypeEnum;
import com.quanyan.common.exception.BizException;
import com.quanyan.common.utils.CommonUtils;
import com.quanyan.common.utils.StringUtil;
import com.quanyan.order.entity.*;
import com.quanyan.order.enums.OrderStatusEnum;
import com.quanyan.order.exception.OrderExceptionEnum;
import com.quanyan.order.mapper.*;
import com.quanyan.order.service.OrderService;
import com.quanyan.orderpay.request.*;
import com.quanyan.orderpay.response.mq.RefundNotifyMsg;
import com.quanyan.pay.enums.RefundStatusEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author songzj
 * @date 16/6/4-17:10
 */
@Service("orderService")
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderRefundMapper orderRefundMapper;

    @Autowired
    private OrderProductMapper orderProductMapper;

    @Autowired
    private UOrderMapper uOrderMapper;

    @Autowired
    private OrderProductRefundMapper orderProductRefundMapper;

    private Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);


    /**
     * 插入订单明细
     *
     * @param order
     * @param orderSaveApiRequest
     * @return
     */
    private List<OrderProduct> insertOrderProductList(Order order, APIRequest<ReqOrderSave> orderSaveApiRequest) {
        List<ReqProductDetail> orderProducts = orderSaveApiRequest.getData().getProductDetailList();

        if (orderProducts == null || orderProducts.size() == 0) {
            return new ArrayList<OrderProduct>(0);
        }
        ReqProductDetail reqProductDetail = null;
        OrderProduct orderProduct = null;

        int length = orderProducts.size();
        List<OrderProduct> orderProductList = new ArrayList<OrderProduct>(length);
        for (int i = 0; i < length; i++) {
            reqProductDetail = orderProducts.get(i);
            orderProduct = new OrderProduct();
            orderProduct.setOrderId(order.getId());
            orderProduct.setProductId(reqProductDetail.getProductId());
            orderProduct.setProductName(reqProductDetail.getProductName());
            orderProduct.setProductDes(reqProductDetail.getProductDesc());
            orderProduct.setProductUrl(reqProductDetail.getProductURL());
            orderProduct.setShowUrl(reqProductDetail.getShowURL());
            orderProduct.setPrice(reqProductDetail.getPrice());
            orderProduct.setQuantity(reqProductDetail.getQuantity());
            orderProduct.setSourceSysId(order.getSourceSystemId());
            orderProduct.setSourceBusinessId(order.getSourceBusinessId());
            this.orderProductMapper.insertSelective(orderProduct);
            orderProductList.add(orderProduct);
        }
        return orderProductList;
    }


    @Override
    public int updateOrderPaySuccess(String orderNo, Integer payId, String payName, Date payTime) {

        OrderExample orderExample = new OrderExample();
        OrderExample.Criteria criteria = orderExample.createCriteria();
        Order order = new Order();
        order.setPayId(payId);
        order.setPayName(payName);
        order.setPayTime(payTime);
        order.setPayState(PAY_STATE_PAYED);
        //订单状态不为超时未支付
        criteria.andOrderNoEqualTo(orderNo).andOrderStateNotEqualTo(OrderStatusEnum.ORDER_STAE_CLOSED.getId());
        order.setOrderState(OrderStatusEnum.ORDER_STATE_CHECKED.getId());

        int paycount=this.orderMapper.updateByExampleSelective(order, orderExample);
        if(paycount==1){
            return 1;
        }else{
            //订单状态不是未支付设置成超时支付状态
            orderExample.clear();
            criteria = orderExample.createCriteria();
            criteria.andOrderNoEqualTo(orderNo);
            order.setOrderState(OrderStatusEnum.ORDER_STAE_CLOSED.getId());
            int closecount=this.orderMapper.updateByExampleSelective(order, orderExample);
            if(closecount==1){
                return 3;
            }else{
                return -1;
            }
        }


    }

    @Override
    public Order selectOrderByOrderNo(Integer orderId, String orderNo) {
        return this.selectOrderByProperties(orderId, orderNo);
    }

    /**
     * 新增订单主体
     *
     * @param orderSaveApiRequest
     * @return
     */
    public Order insertOrderEntity(APIRequest<ReqOrderSave> orderSaveApiRequest) {

        //判断订单是否存在. 是否重复下单.
        ReqOrderSave reqOrderSave = orderSaveApiRequest.getData();
//        if((null!=reqOrderSave.getVer()&&reqOrderSave.getVer().equals("2.0.0.1"))||
//                (null!=reqOrderSave.getMchId()&&reqOrderSave.getMchId().equals(3)&& null!=reqOrderSave.getPlatformType()
//                        &&(reqOrderSave.getPlatformType().equals(PlatformTypeEnum.H5.getId())||reqOrderSave.getPlatformType().equals(PlatformTypeEnum.WEIXIN.getId())))){
//            reqOrderSave.setMchId(3);
//        } else
        if (reqOrderSave.getMchId().equals(9999)) { // 小程序临时解决方案，2017年2月后可删除
            // do nothing
        } else{
            reqOrderSave.setMchId(2);
        }
        OrderExample orderExample = new OrderExample();
        OrderExample.Criteria orderCriteria = orderExample.createCriteria();
        orderCriteria.andSourceSystemIdEqualTo(reqOrderSave.getSourceSystemId());
        orderCriteria.andSourceBusinessIdEqualTo(reqOrderSave.getSourceBusinessId());
        orderCriteria.andOutTradeNoEqualTo(reqOrderSave.getOutTradeNo());
        //防止重复下单 一个外部订单对应一个订单号
//        if (!StringUtil.isBlankOrNull(reqOrderSave.getOrderNo())) {
//            orderCriteria.andOrderNoEqualTo(reqOrderSave.getOrderNo());
//        }
        List<Order> orders = this.orderMapper.selectByExampleWithBLOBs(orderExample);
        if (orders != null && orders.size() > 0) {
            Order order = orders.get(0);
            if(null!=order.getOrderState()&&order.getOrderState().equals(OrderStatusEnum.ORDER_STAE_CLOSED.getId())){
                throw new BizException(OrderExceptionEnum.ORDER_CLOSE);
            }else if (order.getOrderAmount().compareTo(reqOrderSave.getOrderAmount()) == 0
                    && order.getPayState().equals(PAY_STATE_UN_PAYED)
                    && order.getOrderState().equals(OrderStatusEnum.ORDER_STATE_UNCHECKED.getId())) {
                if (!reqOrderSave.getMchId().equals(order.getMchId())) {
                    order.setMchId(reqOrderSave.getMchId());
                    orderMapper.updateByPrimaryKeySelective(order);
                }
                return order;
            } else if (order.getOrderAmount().compareTo(reqOrderSave.getOrderAmount()) == 0
                    && (!order.getPayState().equals(PAY_STATE_UN_PAYED)
                    || !order.getOrderState().equals(OrderStatusEnum.ORDER_STATE_UNCHECKED.getId())
            )) {
                throw new BizException(OrderExceptionEnum.ORDER_HAD_PAYED);
            } else {
                throw new BizException(OrderExceptionEnum.ORDER_AMOUNT_DIFFRENT);
            }
        }

        Order order = new Order();

        order.setSourceSystemId(reqOrderSave.getSourceSystemId());
        order.setSourceBusinessId(reqOrderSave.getSourceBusinessId());
        order.setOrderNo(CommonUtils.generateOrderNo(reqOrderSave.getUid()));
        order.setOutTradeNo(reqOrderSave.getOutTradeNo());
        order.setUid(reqOrderSave.getUid());
        order.setChannelId(reqOrderSave.getChannelId());
        order.setContactName(reqOrderSave.getContactName());
        order.setContactMobile(reqOrderSave.getContactMobile());
        order.setOrderAmount(reqOrderSave.getOrderAmount().setScale(2,BigDecimal.ROUND_DOWN));
        if(order.getOrderAmount().compareTo(new BigDecimal(0))==0){
            order.setOrderState(OrderStatusEnum.ORDER_STATE_CHECKED.getId());
            order.setPayState(PAY_STATE_PAYED);
        }else{
            order.setOrderState(OrderStatusEnum.ORDER_STATE_UNCHECKED.getId());
            order.setPayState(PAY_STATE_UN_PAYED);
        }

        order.setMchId(reqOrderSave.getMchId());
        order.setPayAmount(reqOrderSave.getOrderAmount());
        order.setPayNote(reqOrderSave.getPayNote());
        order.setIsDelete(Constants.IS_DELETE_FALSE);
        order.setPlatFormType(reqOrderSave.getPlatformType());
        order.setOrderSubject(reqOrderSave.getOrderSubject() == null ? reqOrderSave.getOrderDescribe() : reqOrderSave.getOrderSubject());
        order.setOrderDescribe(reqOrderSave.getOrderDescribe());
        order.setNotifyUrl(reqOrderSave.getNotifyURL());
        order.setCloseNotifyUrl(reqOrderSave.getCloseNotifyURL());
        order.setExceptionRefundNotify(reqOrderSave.getExceptionRefundNotify());
        order.setRefundNotifyUrl(reqOrderSave.getRefundNotifyURL());
        order.setPayConfirmNotifyUrl(reqOrderSave.getPayConfirmNotifyURL());
        order.setOrderUrl(reqOrderSave.getOrderURL());
        order.setShowUrl(reqOrderSave.getShowURL());
        order.setExtraParam(reqOrderSave.getExtraParam());
        order.setService(reqOrderSave.getService());

        this.orderMapper.insertSelective(order);
        this.insertOrderProductList(order, orderSaveApiRequest);
        return order;
    }


    @Override
    public APIResponse<OrderRefund> refundApply(ReqOrderRefund reqOrderRefund, String refundOrderNo, BigDecimal totalRefundRmbAmount) {

        logger.warn("订单系统开始处理用户退款申请: " + reqOrderRefund.toString());

        OrderRefundExample orderRefundExample = new OrderRefundExample();
        OrderRefundExample.Criteria criteria = orderRefundExample.createCriteria();
        criteria.andSourceSysCodeEqualTo(reqOrderRefund.getSourceSystemId());
        criteria.andSourceBusinessCodeEqualTo(reqOrderRefund.getSourceBusinessId());
        criteria.andOutTradeRefundNoEqualTo(reqOrderRefund.getOutTradeRefundNo());
        List<OrderRefund> orderRefunds = this.orderRefundMapper.selectByExample(orderRefundExample);
        if (!orderRefunds.isEmpty()) {
            return APIResponse.returnSuccess(orderRefunds.get(0));
        }

        OrderRefund orderRefund = this.insertOrderRefund(reqOrderRefund, refundOrderNo, totalRefundRmbAmount);

        List<ReqRefundProduct> reqRefundProducts = reqOrderRefund.getRefundProductList();
        if (!reqRefundProducts.isEmpty()) {
            for (ReqRefundProduct refundProduct : reqRefundProducts) {
                OrderProductRefund orderProductRefund = new OrderProductRefund();
                orderProductRefund.setSourceSysCode(reqOrderRefund.getSourceSystemId());
                orderProductRefund.setSourceBusinessCode(reqOrderRefund.getSourceBusinessId());
                orderProductRefund.setOrderNo(orderRefund.getOrderNo());
                orderProductRefund.setRefundOrderNo(orderRefund.getRefundOrderNo());
                orderProductRefund.setProductId(refundProduct.getProductId());
                orderProductRefund.setProductName(refundProduct.getProductName());
                orderProductRefund.setQuantity(refundProduct.getQuantity());
                orderProductRefund.setPrice(refundProduct.getPrice());
                orderProductRefund.setStatus(ORDER_REFUND_STATUS_NO);
                this.orderProductRefundMapper.insertSelective(orderProductRefund);
            }
        }

        return APIResponse.returnSuccess(orderRefund);
    }

    private OrderRefund insertOrderRefund(ReqOrderRefund reqOrderRefund, String refundOrderNo, BigDecimal totalRefunAmount) {
        //退款金额 <= 支付金额 - 累计退款金额
        OrderRefund orderRefund = new OrderRefund();
        orderRefund.setSourceSysCode(reqOrderRefund.getSourceSystemId().toString());
        orderRefund.setSourceBusinessCode(reqOrderRefund.getSourceBusinessId().toString());
        orderRefund.setRefundOrderNo(refundOrderNo);
        orderRefund.setOrderNo(reqOrderRefund.getOrderNo());
        orderRefund.setOutTradeRefundNo(reqOrderRefund.getOutTradeRefundNo());
        orderRefund.setApplyUid(reqOrderRefund.getUid());
        orderRefund.setApplyComment(reqOrderRefund.getReason());
        orderRefund.setApplyTime(new Date());
        orderRefund.setRefundAmount(totalRefunAmount);
        orderRefund.setAuditStatus(Constants.AUDIT_STATUS_AGREE); //默认已审核
        orderRefund.setAuditUid(0);
        orderRefund.setAuditComment("系统自动审核");
        orderRefund.setRefundStatus(ORDER_REFUND_STATUS_NO); //未退款
        this.orderRefundMapper.insertSelective(orderRefund);
        logger.warn("新增用户退款记录成功! 退款单号: " + orderRefund.getRefundOrderNo() + ", 原订单号: " + orderRefund.getOrderNo());
        return orderRefund;
    }


    @Override
    public APIResponse<ApiResponseEnum> auditRefundApply(ReqAuditEntity reqAuditEntity) {

        OrderRefund orderRefund = new OrderRefund();
        orderRefund.setAuditUid(reqAuditEntity.getAuditUid());
        orderRefund.setAuditComment(reqAuditEntity.getAuditComment());
        orderRefund.setAuditStatus(reqAuditEntity.getAuditStatus());
        orderRefund.setAuditTime(new Date());

        OrderRefundExample orderRefundExample = new OrderRefundExample();
        OrderRefundExample.Criteria criteria = orderRefundExample.createCriteria();
        criteria.andOrderNoEqualTo(reqAuditEntity.getBusinessId());
        criteria.andAuditStatusEqualTo(Constants.AUDIT_STATUS_INIT);
        int result = this.orderRefundMapper.updateByExampleSelective(orderRefund, orderRefundExample);
        logger.warn("退款申请审核结果: 订单号: " + reqAuditEntity.getBusinessId() + "操作结果" + result + ", 审核人: " + reqAuditEntity.getAuditUid() + ", 原因:" + reqAuditEntity.getAuditComment());
        if (result > 0 && reqAuditEntity.getAuditStatus().equals(Constants.AUDIT_STATUS_AGREE)) {
            return APIResponse.returnSuccess(ApiResponseEnum.SUCCESS);
        } else {
            return APIResponse.returnFail(ApiResponseEnum.FAIL);
        }
    }

    @Override
    public boolean cancelOrder(ReqOrderCancel data) {

        Order update = new Order();
        update.setOrderState(OrderStatusEnum.ORDER_STATE_CANCELED.getId());

        OrderExample orderExample = new OrderExample();
        OrderExample.Criteria criteria = orderExample.createCriteria();
        criteria.andOrderNoEqualTo(data.getOrderNo());

        int i = this.orderMapper.updateByExampleSelective(update, orderExample);
        return i > 0;
    }

    @Override
    public boolean closeOrder(int orderId) {
        return updateOrderStatus(orderId, OrderStatusEnum.ORDER_STAE_CLOSED);
    }

    @Override
    public boolean updateOrderStatus(int orderId, OrderStatusEnum orderStatusEnum) {
        Order update = new Order();
        update.setOrderState(orderStatusEnum.getId());

        OrderExample example = new OrderExample();
        OrderExample.Criteria criteria = example.createCriteria();
        criteria.andIdEqualTo(orderId).andOrderStateEqualTo(OrderStatusEnum.ORDER_STATE_UNCHECKED.getId());

        int i = this.orderMapper.updateByExampleSelective(update, example);
        return i > 0;
    }


    @Override
    public boolean refundComplateProcess(RefundNotifyMsg refundNotifyMsg) {

        OrderRefundExample orderRefundExample = new OrderRefundExample();
        OrderRefundExample.Criteria criteria = orderRefundExample.createCriteria();
        criteria.andOrderNoEqualTo(refundNotifyMsg.getOrderNo());
        criteria.andRefundOrderNoEqualTo(refundNotifyMsg.getRefundOrderNo());

        List<OrderRefund> orderRefunds = this.orderRefundMapper.selectByExample(orderRefundExample);
        if (orderRefunds.isEmpty()) {
            throw new BizException(OrderExceptionEnum.ORDER_REFUND_DO_NOT_EXISTS);
        }

        OrderRefund update = new OrderRefund();
        if (refundNotifyMsg.getRefundState().equals(RefundStatusEnum.CHANGE.getId())
                || refundNotifyMsg.getRefundState().equals(RefundStatusEnum.FAIL.getId())) { //退款失败
            update.setRefundStatus(ORDER_REFUND_STATUS_FAIL);
            //减去退款中金额. 修改退款状态
            this.uOrderMapper.orderRefundFail(refundNotifyMsg.getOrderNo(), refundNotifyMsg.getRefundAmount());
        } else if (refundNotifyMsg.getRefundState().equals(RefundStatusEnum.SUCCESS.getId())) { //退款成功
            update.setRefundStatus(ORDER_REFUND_STATUS_YES);
            this.uOrderMapper.orderRefundSuccess(refundNotifyMsg.getOrderNo(), refundNotifyMsg.getRefundAmount());
        }

        OrderRefundExample orderExample = new OrderRefundExample();
        OrderRefundExample.Criteria orderCriteria = orderExample.createCriteria();
        orderCriteria.andOrderNoEqualTo(refundNotifyMsg.getOrderNo());
        orderCriteria.andRefundOrderNoEqualTo(refundNotifyMsg.getRefundOrderNo());
        if (!StringUtil.isBlankOrNull(refundNotifyMsg.getOutTradeRefundOrderNo())) {
            orderCriteria.andOutTradeRefundNoEqualTo(refundNotifyMsg.getOutTradeRefundOrderNo());
        }
        int result = this.orderRefundMapper.updateByExampleSelective(update, orderExample);
        return result == 1;
    }

    @Override
    public APIResponse refundCompleteProcess(String refundOrderNo, String result) {
        //订单退款更新
        OrderRefund orderRefund=new OrderRefund();
        OrderRefundExample orderRefundExample=new OrderRefundExample();
        orderRefundExample.createCriteria().andRefundOrderNoEqualTo(refundOrderNo);
        //订单商品退款更新
        OrderProductRefund orderProductRefund=new OrderProductRefund();
        OrderProductRefundExample orderProductRefundExample=new OrderProductRefundExample();
        orderProductRefundExample.createCriteria().andRefundOrderNoEqualTo(refundOrderNo);
        if(result.equals(RefundStatusEnum.SUCCESS.getCode())){
            orderRefund.setRefundStatus(ORDER_REFUND_STATUS_YES);
            orderRefundMapper.updateByExampleSelective(orderRefund,orderRefundExample);
            orderProductRefund.setStatus(ORDER_REFUND_STATUS_YES);
            orderProductRefundMapper.updateByExampleSelective(orderProductRefund,orderProductRefundExample);
        }else if(result.equals(RefundStatusEnum.FAIL.getCode())){
            orderRefund.setRefundStatus(ORDER_REFUND_STATUS_FAIL);
            orderRefundMapper.updateByExampleSelective(orderRefund,orderRefundExample);
            orderProductRefund.setStatus(ORDER_REFUND_STATUS_FAIL);
            orderProductRefundMapper.updateByExampleSelective(orderProductRefund,orderProductRefundExample);
        }
        return APIResponse.returnSuccess(ApiResponseEnum.SUCCESS);
    }

    @Override
    public List<ReqRefundProduct> selectOrderProductByOrderNo(Integer orderId) {
        List<ReqRefundProduct> reqRefundProductList=new ArrayList<ReqRefundProduct>();
        OrderProductExample orderProductExample=new OrderProductExample();
        orderProductExample.createCriteria().andOrderIdEqualTo(orderId);
        List<OrderProduct> orderProductList=orderProductMapper.selectByExample(orderProductExample);
        for(OrderProduct orderProduct:orderProductList){
            ReqRefundProduct reqRefundProduct=new ReqRefundProduct();
            reqRefundProduct.setProductId(orderProduct.getProductId());
            reqRefundProduct.setProductName(orderProduct.getProductName());
            reqRefundProduct.setPrice(orderProduct.getPrice());
            reqRefundProduct.setQuantity(orderProduct.getQuantity());
            reqRefundProductList.add(reqRefundProduct);
        }
        return reqRefundProductList;
    }

    @Override
    public Order selectByOrderInfo(ReqOrderInfo reqOrderInfo) {
        OrderExample orderExample=new OrderExample();
        OrderExample.Criteria criteria=orderExample.createCriteria();
        if(null!=reqOrderInfo.getOrderNo()){
            criteria.andOrderNoEqualTo(reqOrderInfo.getOrderNo());
        }else if(null!=reqOrderInfo.getOutTradeNo()){
            criteria.andOutTradeNoEqualTo(reqOrderInfo.getOutTradeNo());
        }
        if(null!=reqOrderInfo.getUid()){
            criteria.andUidEqualTo(reqOrderInfo.getUid());
        }
        List<Order> orderList=orderMapper.selectByExample(orderExample);
        if(orderList.isEmpty()){
            return null;
        }else{
            return orderList.get(0);
        }

    }

    @Override
    public List<Order> selectByExample(OrderExample orderExample) {

        return orderMapper.selectByExample(orderExample);
    }

    @Override
    public void updateOrderPayId(String orderNo, Integer payId) {
        OrderExample orderExample = new OrderExample();
        orderExample.createCriteria().andOrderNoEqualTo(orderNo);
        Order order = new Order();
        order.setPayId(payId);
        orderMapper.updateByExampleSelective(order,orderExample);
    }


    private Order selectOrderByProperties(Integer id, String orderNo) {
        if (id != null) {
            return this.orderMapper.selectByPrimaryKey(id);
        }

        if (StringUtil.isBlankOrNull(orderNo)) {
            throw new BizException(ApiResponseEnum.PARAMETER_CANT_BE_EMPTY);
        }

        OrderExample orderExample = new OrderExample();
        OrderExample.Criteria criteria = orderExample.createCriteria();
        if (!StringUtil.isBlankOrNull(orderNo)) {
            criteria.andOrderNoEqualTo(orderNo);
        }

        List<Order> orders = this.orderMapper.selectByExampleWithBLOBs(orderExample);
        if (orders == null || orders.size() == 0) {
            throw new BizException(ApiResponseEnum.RECORD_DO_NOT_EXISTS);
        }

        return orders.get(0);
    }

    private List<OrderProduct> selectProductDetailList(Integer orderId) {
        OrderProductExample orderProductExample = new OrderProductExample();
        OrderProductExample.Criteria criteria = orderProductExample.createCriteria();
        criteria.andOrderIdEqualTo(orderId);
        return this.orderProductMapper.selectByExample(orderProductExample);
    }
}
